
package com.kim.ping.Service

import org.slf4j.LoggerFactory
import org.springframework.http.HttpStatus
import org.springframework.http.MediaType
import org.springframework.web.reactive.function.client.ClientResponse
import org.springframework.web.reactive.function.client.WebClient
import reactor.core.publisher.Mono
import spock.lang.Specification

class PingServiceSpec extends Specification {

    def logger = LoggerFactory.getLogger(PingServiceSpec.class)
    def webClient = WebClient.create("http://localhost:8083");
    def pingService = new PingService(webClient)

    def "ping should call pong service and log response"() {
        given:
        def trackingNumber = "uuid - "
        def expectedResponse = "Pong Response"
        def clientResponse = Mock(ClientResponse)
        def webClientResponseSpec = Mock(WebClient.ResponseSpec)
        def requestHeadersUriSpec = Mock(WebClient.RequestHeadersUriSpec)
        def requestHeadersSpec = Mock(WebClient.RequestHeadersSpec)

        when:
        pingService.ping()

        then:
        0 * webClient.get() >> requestHeadersUriSpec
        0 * requestHeadersUriSpec.uri("/pong") >> requestHeadersSpec
        0 * requestHeadersSpec.accept(MediaType.TEXT_PLAIN) >> requestHeadersSpec
        0 * requestHeadersSpec.retrieve() >> webClientResponseSpec
        0 * webClientResponseSpec.onStatus(HttpStatus::is4xxClientError, _) >> webClientResponseSpec
        0 * webClientResponseSpec.bodyToMono(String.class) >> Mono.just(expectedResponse)
        0 * logger.info(trackingNumber + " start to call pong.")
        0 * logger.info(trackingNumber + " Request send & Pong response : " + expectedResponse)
    }

    def "ping should handle 4xx client errors gracefully"() {
        given:
        def trackingNumber = "uuid - "
        def clientResponse = Mock(ClientResponse)
        def webClientResponseSpec = Mock(WebClient.ResponseSpec)
        def requestHeadersUriSpec = Mock(WebClient.RequestHeadersUriSpec)
        def requestHeadersSpec = Mock(WebClient.RequestHeadersSpec)

        when:
        pingService.ping()

        then:
        0 * webClient.get() >> requestHeadersUriSpec
        0 * requestHeadersUriSpec.uri("/pong") >> requestHeadersSpec
        0 * requestHeadersSpec.accept(MediaType.TEXT_PLAIN) >> requestHeadersSpec
        0 * requestHeadersSpec.retrieve() >> webClientResponseSpec
        0 * webClientResponseSpec.onStatus(HttpStatus::is4xxClientError, _) >> {
            ClientResponse response ->
                logger.info(trackingNumber + "Request send & Pong throttled it.")
                return Mono.empty()
        }
        0 * logger.info(trackingNumber + " start to call pong.")
        0 * logger.info(trackingNumber + "Request send & Pong throttled it.")
    }
}